/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package baseDatos;

import entidades.Bateria;
import entidades.Camara;
import entidades.EstadoJaula;
import entidades.Jaula;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Facundo
 */
public class JaulaDAO {

    private String query;
    private Connection conDB;
    private PreparedStatement pst;
    private static int codigo_bateria;

    public JaulaDAO(Connection con) {
        this.conDB = con;
    }

    public JaulaDAO() {
    }

    /**
     * @return the query
     */
    public String getQuery() {
        return query;
    }

    /**
     * @param query the query to set
     */
    public void setQuery(String query) {
        this.query = query;
    }

    /**
     * @return the conDB
     */
    public Connection getConDB() {
        return conDB;
    }

    /**
     * @param conDB the conDB to set
     */
    public void setConDB(Connection conDB) {
        this.conDB = conDB;
    }

    /**
     * @return the pst
     */
    public PreparedStatement getPst() {
        return pst;
    }

    /**
     * @param pst the pst to set
     */
    public void setPst(PreparedStatement pst) {
        this.pst = pst;
    }

    /*
     * Metodo que modifica el estado de una jaula. Recibe como parametro el codigo de la jaula y
     * el codigo del estado
     * Retorna true en caso afirmativo y false en caso contrario
     */
    public boolean updateEstadoJaula(int codigoJaula, int codigoEstado) {
        System.out.println("Actualizando el estado de la jaula....");
        Jaula aux = null;
        try {
            /*
             * Verificar que la juala exista previamente
             */
            aux = this.getJaula(codigoJaula);
            if (aux != null) {
                setQuery("update PC_JAULA set codigo_estado=" + codigoEstado
                        + " where codigo_jaula=" + codigoJaula);
                System.out.println("Sentencia que se usa para actualizar la jaula: " + this.getQuery());
                setPst(getConDB().prepareStatement(getQuery()));
                getPst().executeQuery();
                getPst().close();
            } else {
                return false;
            }
        } catch (SQLException ex) {
            Logger.getLogger(JaulaDAO.class.getName()).log(Level.SEVERE, null, ex);
            System.out.println("Excepcion: " + ex.getMessage() + ". Sentencia utilizada: " + this.getQuery());
        }
        return true;
    }

    /*
     * Metodo que modifica el estado de una jaula. Recibe como parametro un objeto Camara y
     * un objeto estado. La camara debe tener un array con una bateria y la bateria debe tener un
     * array con una jaula.
     * Retorna true en caso afirmativo y false en caso contrario
     */
    public boolean updateEstadoJaula(Camara cam, EstadoJaula estado) {
        Jaula aux = null;
        /*
         * Aka, se declara un iterator para el recorrer un array de baterias, perteneciente a una
         * determinada camara. Luego se declara otro iterator para recorrer un array de jaulas
         * pertenecientes a una determinada bateria.
         */
        Iterator iter = cam.getBateria().iterator();
        Bateria bat = (Bateria) iter.next();
        Iterator iter2 = bat.getJaula().iterator();
        Jaula jau = (Jaula) iter2.next();
        /*
         * Luego de obtenida la jaula y la bateria, ya que la camara ya la teniamos a trvez del animal,
         * debemos obtener el codigo de cada una de ellas, para poder insertar el codigo de la jaula,
         * en la tabla animal.
         */
        int codigoTipoCamara = new TipoCamaraDAO(this.getConDB()).devolverCodigoCamara(cam.getTipo_camara().getNombre());
        int codigoCamara = new CamaraDAO(this.getConDB()).getCodigoCamara(cam.getNombre(), codigoTipoCamara);
        int codigoBateria = new BateriaDAO(this.getConDB()).devolverCodigoBateria(bat.getNombre(), codigoCamara);
        int codigoJaula = new JaulaDAO(this.getConDB()).devolverCodigoJaula(jau.getNombre(), codigoBateria);
        int codigoEstado = new EstadoJaulaDAO(this.getConDB()).devolverCodigoEstadoJaula(estado);

        try {
            /*
             * Verificar que la juala exista previamente
             */
            aux = this.getJaula(codigoJaula);
            if (aux != null) {
                setQuery("update PC_JAULA set codigo_estado=" + codigoEstado
                        + " where codigo_jaula=" + codigoJaula);
                setPst(getConDB().prepareStatement(getQuery()));
                getPst().executeQuery();
                getPst().close();
            } else {
                return false;
            }
        } catch (SQLException ex) {
            Logger.getLogger(JaulaDAO.class.getName()).log(Level.SEVERE, null, ex);
        }
        return true;
    }

    /*
     * Metodo que devuelve un solo objeto Jaula de acuerdo a la bateria que pertence y su nombre
     */
    public Jaula getJaula(int codigoBateria, String nombre) {
        Jaula jau = null;
        setQuery("select * from PC_JAULA where codigo_bateria =" + codigoBateria + " and nombre='" + nombre + "'");
        jau = this.devolverJaula(getQuery());
        return jau;
    }

    /*
     * Metodo que recibe como parametro el codigo de una jaula. Utiliza el metodo
     * devolverJaula() pasandole como parametro la sentencia y devuelve
     * un objeto Jaula
     */
    public Jaula getJaula(int codigo) {
        Jaula jau = null;
        setQuery("select * from PC_JAULA where codigo_jaula =" + codigo);
        jau = this.devolverJaula(getQuery());
        return jau;
    }

    /*
     * Metodo que recibe como parametro el codigo de una jaula y el codigo de un estado.
     * Utiliza el metodo devolverJaula() pasandole como parametro la sentencia y devuelve
     * un objeto Jaula si la jaula se corresponde con ese estado pasado por parametro y null en caso
     * contrario.
     */
    public Jaula getJaulaEstado(int codigo, int codigoEstado) {
        Jaula jau = null;
        setQuery("select * from PC_JAULA where codigo_jaula =" + codigo + " and codigo_estado=" + codigoEstado);
        jau = this.devolverJaula(getQuery());
        return jau;
    }

    /*
     * metodo que devuelve una determinada jaula. Recibe como parametro la sentencia de busqueda
     */
    private Jaula devolverJaula(String sentencia) {
        Jaula jau = null;
        ResultSet rs = null;
        setQuery(sentencia);
        try {
            setPst(getConDB().prepareStatement(getQuery()));
            rs = getPst().executeQuery();
            while (rs.next()) {
                jau = new Jaula();
                jau.setNombre(rs.getString("nombre"));
                if (rs.getString("descripcion") != null) {
                    jau.setDescripcion(rs.getString("descripcion"));
                }
                jau.setEstado(new EstadoJaulaDAO(this.getConDB()).getEstadoJaula(rs.getInt("codigo_estado")));
            }
            getPst().close();
            rs.close();
            return jau;
        } catch (SQLException ex) {
            Logger.getLogger(JaulaDAO.class.getName()).log(Level.SEVERE, null, ex);
        }
        return jau;
    }

    /*
     * Metodo que retorna un ArrayList con todas las jaulas de una determinada bateria y estado de jaula
     */
    public ArrayList getJaulaBateriaEstado(int estadoJaula, int bateria) {
        ArrayList todos = null;
        setQuery("select * from PC_JAULA where codigo_bateria =" + bateria + " and codigo_estado=" + estadoJaula);
        System.out.println("Sentencia que trae las jaulas segun bateria y estado: " + this.getQuery());
        todos = this.devolverJaulas(getQuery());
        return todos;
    }

    /*
     * Metodo que devuelve un arrayList de jaulas de acuerdo al codigo de una bateria recibida
     * por parametro..
     */
    public ArrayList getJaulas(int bateria) {
        ArrayList todos = null;
        setQuery("select * from PC_JAULA where codigo_bateria =" + bateria);
        todos = this.devolverJaulas(getQuery());
        return todos;
    }

    /*
     * Metodo que retorna un arrayList de jaulas, de acuerdo a la sentencia
     * recibida como parametro de entrada
     */
    private ArrayList devolverJaulas(String sentencia) {
        try {
            ArrayList todos = null;
            Jaula jau = null;
            ResultSet rs;
            setQuery(sentencia);
            todos = new ArrayList();
            System.out.println("Sentencia para devolver jaulas:" + sentencia);
            setPst(getConDB().prepareStatement(sentencia));
            rs = getPst().executeQuery();
            while (rs.next()) {
                jau = new Jaula();
                jau.setNombre(rs.getString("nombre"));
                if (rs.getString("descripcion") != null) {
                    jau.setDescripcion(rs.getString("descripcion"));
                }
                jau.setEstado(new EstadoJaulaDAO(this.getConDB()).getEstadoJaula(rs.getInt("codigo_estado")));
                todos.add(jau);
            }
            rs.close();
            getPst().close();
            return todos;
        } catch (SQLException ex) {
            Logger.getLogger(JaulaDAO.class.getName()).log(Level.SEVERE, null, ex);
            System.out.println("Excepcion: " + ex.getMessage() + ", sentencia utilizada: " + this.getQuery());
        }
        return null;
    }

    /*
     * metodo que devuelve el nombre de una bateria a la que pertenece la jaula pasada por parametro
     */
    /*
    public String nombreBateriaPorJaula(String nombreJaula) {
    String nombreBateria = null;
    ResultSet rs = null;
    setQuery("select cod_bateria from Jaula where nombre = '" + nombreJaula + "'");
    try {
    setPst(getConDB().prepareStatement(getQuery()));
    rs = getPst().executeQuery();
    while (rs.next()) {

    nombreBateria = rs.getString("cod_bateria");
    return nombreBateria;
    }
    getPst().close();
    rs.close();
    } catch (SQLException ex) {
    Logger.getLogger(AnimalDAO.class.getName()).log(Level.SEVERE, null, ex);
    }
    return nombreBateria;
    }
     *
     */

    /*
     * metodo que devuelve el codigo de una jaula, recibe por parametro el nombre de la jaula y el
     * codigo de la bateria.
     */
    public int devolverCodigoJaula(String nombre, int codigoBateria) {
        int codigoJaula = -1;
        ResultSet rs = null;
        setQuery("select codigo_jaula from PC_JAULA where nombre='" + nombre + "' and codigo_bateria=" + codigoBateria);
        try {
            setPst(getConDB().prepareStatement(getQuery()));
            rs = getPst().executeQuery();
            while (rs.next()) {
                codigoJaula = rs.getInt("codigo_jaula");
            }
            getPst().close();
            rs.close();
        } catch (SQLException ex) {
            Logger.getLogger(JaulaDAO.class.getName()).log(Level.SEVERE, null, ex);
        }
        return codigoJaula;
    }

    public int devolverCodigoJaula(String nombre) {
        int codigoJaula = -1;
        ResultSet rs = null;
        setQuery("select codigo_jaula from PC_JAULA where nombre='" + nombre + "'");
        try {
            setPst(getConDB().prepareStatement(getQuery()));
            rs = getPst().executeQuery();
            while (rs.next()) {
                codigoJaula = rs.getInt("codigo_jaula");
            }
            getPst().close();
            rs.close();
        } catch (SQLException ex) {
            Logger.getLogger(JaulaDAO.class.getName()).log(Level.SEVERE, null, ex);
        }
        return codigoJaula;
    }

    /*
     * metodo que devuelve el codigo de la bateria a la cual pertenece la jaula,
     * recibe por parametro el codigo de la jaula.
     */
    public int devolverCodigoBateria(int codigoJaula) {
        int codigoBateria = -1;
        ResultSet rs = null;
        setQuery("select codigo_bateria from PC_JAULA where codigo_jaula =" + codigoJaula);
        try {
            setPst(getConDB().prepareStatement(getQuery()));
            rs = getPst().executeQuery();
            while (rs.next()) {
                codigoBateria = rs.getInt("codigo_bateria");
            }
            getPst().close();
            rs.close();
        } catch (SQLException ex) {
            Logger.getLogger(JaulaDAO.class.getName()).log(Level.SEVERE, null, ex);
        }
        return codigoBateria;
    }

    public ArrayList getJaulas(int cod_tipoCamara, int cod_estado) {
        try {
            ArrayList res_jaula_disponibles = new ArrayList();
            Jaula res_jaula = null;
            int nro_jaula_i = 1;
            int nro_jaula_f = 1;
            int cant_jaulas_disponibles = 0;
            int cod_bateria = 0;
            for (int i = 1; i < 6; i++) {
                nro_jaula_f = nro_jaula_i + 5;
                String sql = "SELECT count(*) as cant, codigo_bateria FROM PC_JAULA where codigo_estado = 1 "
                        + "and codigo_jaula between " + nro_jaula_i + " and " + nro_jaula_f + " "
                        + " AND codigo_bateria = (SELECT bat.codigo_bateria FROM pc_bateria bat, pc_camara cam WHERE bat.codigo_bateria=cam.codigo_camara "
                        + " AND cam.codigo_tipo_camara = (SELECT codigo_tipo FROM pc_tipo_camara WHERE nombre ='REPRODUCCION')) group by codigo_bateria";
                System.out.println(i + " Sentencia para buscar jaulas disponibles: " + sql);

                this.setPst(this.getConDB().prepareStatement(sql));
                ResultSet rs = this.getPst().executeQuery();
                while (rs.next()) {
                    cant_jaulas_disponibles = rs.getInt("cant");
                    cod_bateria = rs.getInt("codigo_bateria");
                }

                if (cant_jaulas_disponibles == 6) {
                    System.out.println("aca entra");
                    if (res_jaula_disponibles.isEmpty() == true) {
                        for (int j = nro_jaula_i; j <= nro_jaula_f; j++) {
                            res_jaula = new JaulaDAO(this.getConDB()).getJaula(j);
                            System.out.println("Nombre de jaula agregaga al array: " + res_jaula.getNombre());
                            res_jaula_disponibles.add(res_jaula);
                            this.codigo_bateria = cod_bateria;
                            System.out.println("Codigo de la bateria: " + this.codigo_bateria);
                        }
                        return res_jaula_disponibles;
                    } else {
                        System.out.println(res_jaula_disponibles.isEmpty());
                        return res_jaula_disponibles;
                    }
                } else {
                    System.out.println("Cantidad de jaulas disponibles: " + cant_jaulas_disponibles);
                }
                nro_jaula_i += 6;
            }
            return res_jaula_disponibles;
        } catch (SQLException ex) {
            Logger.getLogger(JaulaDAO.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    public int getBateriaDisponible() {
        System.out.println("Devoviendo el codigo de la bateria disponible: " + codigo_bateria);
        return codigo_bateria;
    }

    public int getCantidadGazapos(Camara cam) {
        int cant = 0;
        Jaula aux = null;
        /*
         * Aka, se declara un iterator para el recorrer un array de baterias, perteneciente a una
         * determinada camara. Luego se declara otro iterator para recorrer un array de jaulas
         * pertenecientes a una determinada bateria.
         */
        Iterator iter = cam.getBateria().iterator();
        Bateria bat = (Bateria) iter.next();
        Iterator iter2 = bat.getJaula().iterator();
        Jaula jau = (Jaula) iter2.next();


        int codigoTipoCamara = new TipoCamaraDAO(this.getConDB()).devolverCodigoCamara(cam.getTipo_camara().getNombre());
        int codigoCamara = new CamaraDAO(this.getConDB()).getCodigoCamara(cam.getNombre(), codigoTipoCamara);
        int codigoBateria = new BateriaDAO(this.getConDB()).devolverCodigoBateria(bat.getNombre(), codigoCamara);
        int codigoJaula = new JaulaDAO(this.getConDB()).devolverCodigoJaula(jau.getNombre(), codigoBateria);


        ResultSet rs = null;
        setQuery("select count(*) as cantidad from PC_ANIMAL where codigo_ubicacion =" + codigoJaula);
        try {
            setPst(getConDB().prepareStatement(getQuery()));
            rs = getPst().executeQuery();
            while (rs.next()) {
                cant = rs.getInt("cantidad");
            }
            getPst().close();
            rs.close();
        } catch (SQLException ex) {
            Logger.getLogger(JaulaDAO.class.getName()).log(Level.SEVERE, null, ex);
        }
        return cant;
    }

    public ArrayList getJaulasMaduracionLibre() {
        String sql = "SELECT * FROM pc_jaula WHERE codigo_bateria in "
                + "(SELECT codigo_bateria FROM pc_bateria WHERE codigo_camara = "
                + "( SELECT codigo_camara FROM pc_camara WHERE codigo_tipo_camara= "
                + "( SELECT codigo_tipo FROM pc_tipo_camara WHERE nombre ='MADURACION')))"
                + " and codigo_estado=( SELECT codigo_estado FROM pc_estado_jaula WHERE nombre ='LIBRE')";
        ArrayList res_jaulasMaduracionDisponible = this.devolverJaulas(sql);
        return res_jaulasMaduracionDisponible;
    }
}
